using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

using System.Runtime.InteropServices;

using Microsoft.Kinect;

using BulletSharp;

using KinectMenagerNamespace;
using KinectMenagerNamespace.KinectGestureParts;
using DataTypes;
using System.IO;

namespace KinectGame
{
	using XNA = Microsoft.Xna.Framework;
    using System.Threading;

	public class Game : Microsoft.Xna.Framework.Game
	{
		GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;

		public static GraphicsDevice graphicsDevice;        
		public static DynamicsWorld World;
		public static DebugShapeRenderer DebugShapeRenderer;

		private CollisionConfiguration CollisionConf;
		private CollisionDispatcher Dispatcher;
		private BroadphaseInterface Broadphase;

		public static Dictionary<string, Model> models = new Dictionary<string, Model>();
		private List<Level> levels = new List<Level>();
		private Level activeLevel;
		private GameObject activeObject = null;

		private KinectMenager kinectMenager;

		public static ArcBallCamera Camera;
		private List<Light> lights;
		private Light pointLight;

		private RenderTarget2D shadowRenderTarget;
		private Texture2D shadowMapTexture;

		private RenderTarget2D screenRenderTarget;
		private Texture2D screenMapTexture;

        private Texture2D hand0Texture, hand1Texture, rotateTexture, rotateXTexture, rotateYTexture, rotateZTexture, cameraTexture, objectTexture;

        private int levelCounter = 0;

        private Menu mainMenu, levelsMenu, activeMenu;
        		
		public Game()
		{
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
			kinectMenager = new KinectMenager(FistTrackingMode.None, 10, 50, 50, 50, 5, 2);
            //graphics.IsFullScreen = true;
		}        

		protected override void Initialize()
		{
			spriteBatch = new SpriteBatch(GraphicsDevice);
			graphicsDevice = GraphicsDevice;

			int windowWidth = (int)(GraphicsDevice.DisplayMode.Width);
			int windowHeight = (int)(GraphicsDevice.DisplayMode.Height);

			graphics.SynchronizeWithVerticalRetrace = false;
			graphics.PreferredBackBufferWidth = windowWidth;
			graphics.PreferredBackBufferHeight = windowHeight;
			graphics.PreferMultiSampling = true;
			graphics.ApplyChanges();

            graphics.ToggleFullScreen();

			Camera = new ArcBallCamera(45.0f, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0.12f, 150.0f);
			pointLight = new Light(new Vector3(0.001f, 20.0f, 0), new XNA.Vector4(0.05f, 0.09f, 0.1f, 1.0f), new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f), new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f));
			Light pointLight2 = new Light(new Vector3(30.0f, 10.0f, 30.0f), new XNA.Vector4(0.05f, 0.09f, 0.1f, 1.0f), new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f), new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f));
            Light pointLight3 = new Light(new Vector3(-30.0f, 10.0f, -30.0f), new XNA.Vector4(0.05f, 0.09f, 0.1f, 1.0f), new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f), new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f));


			lights = new List<Light>();
			lights.Add(pointLight);
			lights.Add(pointLight2);
            lights.Add(pointLight3);

			graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

			shadowRenderTarget = new RenderTarget2D(GraphicsDevice, 2048, 2048, true,
				graphicsDevice.PresentationParameters.BackBufferFormat,
				DepthFormat.Depth24Stencil8);

			screenRenderTarget = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);

			DebugShapeRenderer = new DebugShapeRenderer();
			DebugShapeRenderer.Initialize(GraphicsDevice);

			CollisionConf = new DefaultCollisionConfiguration();
			Dispatcher = new CollisionDispatcher(CollisionConf);

			Broadphase = new DbvtBroadphase();

			World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, null, CollisionConf);
			World.Gravity = new Vector3(0, -9.8f, 0);

            GameObject lowGround = new GameObject(new BoundingBox(new Vector3(-100, -1, -100), new Vector3(100, 1, 100)), Vector3.One, Vector3.Zero, Vector3.Down * 100, 0);
            lowGround.Activate();
            World.AddRigidBody(lowGround.RigidBody);

			kinectMenager.Initialize();
			//kinectMenager.SetWorkArea(-10.0f, 5.0f, -10.0f, 10.0f, 10.0f, 10.0f);            

			KinectGesturePart[] parts1 = new KinectGesturePart[3];
			parts1[0] = new SwipeLeftWithRightHand1();
			parts1[1] = new SwipeLeftWithRightHand2();
			parts1[2] = new SwipeLeftWithRightHand3();
			
			swipeRightHand = new KinectGesture(parts1, new TimeSpan(0, 0, 0, 10));
			kinectMenager.GestureRecognizer.AddGesture(swipeRightHand);
			swipeRightHand.OnGestureSucces += new GestureHandler(swipeRightHand_OnGestureSucces);
			swipeRightHand.Enable();

			KinectGesturePart[] parts2 = new KinectGesturePart[3];
			parts2[0] = new SwipeRightWithLeftHand1();
			parts2[1] = new SwipeRightWithLeftHand2();
			parts2[2] = new SwipeRightWithLeftHand3();

			swipeLeftHand = new KinectGesture(parts2, new TimeSpan(0, 0, 0, 10));
			kinectMenager.GestureRecognizer.AddGesture(swipeLeftHand);
			swipeLeftHand.OnGestureSucces += new GestureHandler(swipeLeftHand_OnGestureSucces);
			swipeLeftHand.Enable();

            KinectGesturePart[] parts3 = new KinectGesturePart[3];
            parts3[0] = new SwipeDownWithRightHand1();
            parts3[1] = new SwipeDownWithRightHand2();
            parts3[2] = new SwipeDownWithRightHand3();

            riseAndDropRightHand = new KinectGesture(parts3, new TimeSpan(0, 0, 0, 10));
            kinectMenager.GestureRecognizer.AddGesture(riseAndDropRightHand);
            riseAndDropRightHand.OnGestureSucces += new GestureHandler(riseAndDropRightHand_OnGestureSucces);            

            KinectGesturePart[] parts4 = new KinectGesturePart[4];
            parts4[0] = new WaveWithLeftHand1();
            parts4[1] = new WaveWithLeftHand2();
            parts4[2] = new WaveWithLeftHand3();
            parts4[3] = new WaveWithLeftHand1();

            waveLeftHand = new KinectGesture(parts4, new TimeSpan(0, 0, 0, 3));
            kinectMenager.GestureRecognizer.AddGesture(waveLeftHand);
            waveLeftHand.OnGestureSucces += new GestureHandler(waveLeftHand_OnGestureSucces);
            waveLeftHand.Enable();

            KinectGesturePart[] parts5 = new KinectGesturePart[4];
            parts5[0] = new WaveWithRightHand1();
            parts5[1] = new WaveWithRightHand2();
            parts5[2] = new WaveWithRightHand3();
            parts5[3] = new WaveWithRightHand1();

            waveRightHand = new KinectGesture(parts5, new TimeSpan(0, 0, 0, 3));
            kinectMenager.GestureRecognizer.AddGesture(waveRightHand);
            waveRightHand.OnGestureSucces += new GestureHandler(waveRightHand_OnGestureSucces);
            waveRightHand.Enable();

            KinectGesturePart[] parts6 = new KinectGesturePart[4];
            parts6[0] = new ClapWithBothHands1();
            parts6[1] = new ClapWithBothHands2();
            parts6[2] = new ClapWithBothHands3();
            parts6[3] = new ClapWithBothHands1();

            clapWithBothHands = new KinectGesture(parts6, new TimeSpan(0, 0, 0, 3));
            kinectMenager.GestureRecognizer.AddGesture(clapWithBothHands);
            clapWithBothHands.OnGestureSucces += new GestureHandler(clapWithBothHands_OnGestureSucces);
            clapWithBothHands.Enable();

            //kinectMenager.SpeechRecognizer.DOWN += new EventHandler(SpeechRecognizer_DOWN);

			base.Initialize();
		}

		protected override void LoadContent()
		{
			font = Content.Load<SpriteFont>("SpriteFont1");
			models.Add("box", Content.Load<Model>("box"));
			models.Add("cylinder", Content.Load<Model>("cylinder"));
			models.Add("sphere", Content.Load<Model>("sphere"));
			models.Add("pyramid", Content.Load<Model>("pyramid"));
			models.Add("ground", Content.Load<Model>("ground"));
            models.Add("newgame", Content.Load<Model>("newgame"));
            models.Add("levels", Content.Load<Model>("levels"));
            models.Add("changehand", Content.Load<Model>("changehand"));
            models.Add("exit", Content.Load<Model>("exit"));
            models.Add("1", Content.Load<Model>("1"));
            models.Add("2", Content.Load<Model>("2"));
            models.Add("3", Content.Load<Model>("3"));
            models.Add("fail", Content.Load<Model>("fail"));
            models.Add("success", Content.Load<Model>("success"));
            models.Add("activeskeleton", Content.Load<Model>("activeskeleton"));
            models.Add("calibration", Content.Load<Model>("calibration"));
            models.Add("FLCH", Content.Load<Model>("FLCH"));
            models.Add("FLOH", Content.Load<Model>("FLOH"));
            models.Add("FRCH", Content.Load<Model>("FRCH"));
            models.Add("FROH", Content.Load<Model>("FROH"));
            models.Add("NLCH", Content.Load<Model>("NLCH"));
            models.Add("NLOH", Content.Load<Model>("NLOH"));
            models.Add("NRCH", Content.Load<Model>("NRCH"));
            models.Add("NROH", Content.Load<Model>("NROH"));
            models.Add("MML", Content.Load<Model>("MML"));
            models.Add("MMR", Content.Load<Model>("MMR"));
            models.Add("preparefor", Content.Load<Model>("preparefor"));
            models.Add("searchingkinect", Content.Load<Model>("searchingkinect"));
            models.Add("activehand", Content.Load<Model>("activehand"));
            models.Add("left", Content.Load<Model>("left"));
            models.Add("right", Content.Load<Model>("right"));
            models.Add("wavetoselect", Content.Load<Model>("wavetoselect"));
            models.Add("none", Content.Load<Model>("none"));
            models.Add("paused", Content.Load<Model>("paused"));
            models.Add("clock", Content.Load<Model>("clock"));

			LevelData[] levelsData = Content.Load<LevelData[]>("levelsData");

			foreach (var level in levelsData)
			{
				levels.Add(new Level(level));
			}

			//activeLevel = levels[levelCounter];            

            hand0Texture = Content.Load<Texture2D>("hand0");
            hand1Texture = Content.Load<Texture2D>("hand1");
            cameraTexture = Content.Load<Texture2D>("camera");
            objectTexture = Content.Load<Texture2D>("object");

            rotateTexture = Content.Load<Texture2D>("rotate");
            rotateXTexture = Content.Load<Texture2D>("rotatex");
            rotateYTexture = Content.Load<Texture2D>("rotatey");
            rotateZTexture = Content.Load<Texture2D>("rotatez");

            mainMenu = new Menu(0, new Vector3(0, 30, -20), 44, 1.34f);
            //mainMenu.OnEscape += new EventHandler(Exit_OnEnter);

            levelsMenu = new Menu(1, new Vector3(0, 30, -10), 64, 1.2f);
            levelsMenu.OnEscape += new EventHandler(LevelMenuExit_OnEnter);

            MenuElement element1 = new MenuElement(models["newgame"], Vector3.One * 2, 0, 20, 10, 0);
            MenuElement element2 = new MenuElement(models["levels"], Vector3.One * 2, 90, 20, 10, 1);
            MenuElement element3 = new MenuElement(models["changehand"], Vector3.One * 2, 180, 20, 10, 2);
            MenuElement element4 = new MenuElement(models["exit"], Vector3.One * 2, 270, 20, 10, 3);

            element1.OnEnter += new EventHandler(NewGame_OnEnter);
            element2.OnEnter += new EventHandler(Levels_OnEnter);
            element3.OnEnter += new EventHandler(ChangeHand_OnEnter);
            element4.OnEnter += new EventHandler(Exit_OnEnter);

            mainMenu.MenuElements.Add(element1);
            mainMenu.MenuElements.Add(element2);
            mainMenu.MenuElements.Add(element3);
            mainMenu.MenuElements.Add(element4);
            
            activeMenu = mainMenu;
            activeMenu.Show();
		}

		protected override void UnloadContent()
		{            
			World.Dispose();
			kinectMenager.Dispose();
		}		
        
		KinectGesture swipeRightHand;
		KinectGesture swipeLeftHand;
        KinectGesture riseAndDropRightHand;
        KinectGesture waveLeftHand;
        KinectGesture waveRightHand;
        KinectGesture clapWithBothHands;

        FistType activeHand = FistType.Right;

		float cameraRotateYTmp = 0;
		float cameraRotateXTmp = 0;

        bool isActiveHand = false;

        void clapWithBothHands_OnGestureSucces(GestureEventArgs args)
        {
            if (activeLevel != null && !kinectMenager.ScaleGestureEnable &&
                !kinectMenager.RotationGestureEnable &&
                !kinectMenager.TranslationGestureEnable)
            {
                if (activeLevel.Status == LevelStatus.Paused)
                {
                    UnPauseLevel();
                }
                else if (activeLevel.Status == LevelStatus.Active)
                {
                    PauseLevel();
                }
            }
        }
		void swipeRightHand_OnGestureSucces(GestureEventArgs args)
		{
			float t = (float)(args.Times[args.Times.Length - 1] - args.Times[1]).TotalSeconds;

            if (activeMenu.State == MenuState.Hidden)
            {
                if (!kinectMenager.RotationGestureEnable &&
                    !kinectMenager.TranslationGestureEnable &&
                    !kinectMenager.ScaleGestureEnable)
                {
                    cameraRotateYTmp += 0.025f / t;
                }
            }
            else
            {
                activeMenu.NextChoice();
            }
		}
		void swipeLeftHand_OnGestureSucces(GestureEventArgs args)
		{
			float t = (float)(args.Times[args.Times.Length - 1] - args.Times[1]).TotalSeconds;

            if (activeMenu.State == MenuState.Hidden)
            {
                if (!kinectMenager.RotationGestureEnable &&
                    !kinectMenager.TranslationGestureEnable &&
                    !kinectMenager.ScaleGestureEnable)
                {
                    cameraRotateYTmp -= 0.025f / t;
                }
            }
            else
            {
                activeMenu.PreviousChoice();
            }
		}
        void waveRightHand_OnGestureSucces(GestureEventArgs args)
        {
            if (kinectMenager.CalibrationFinish)
            {
                if (activeMenu != null && activeMenu.State == MenuState.Visible && isActiveHand)
                {
                    activeMenu.InvokeOnEscape();
                }

                if(activeLevel == null && !isActiveHand)
                {
                    activeHand = FistType.Right;
                    riseAndDropRightHand.Enable();
                    waveLeftHand.Disable();
                    if (kinectMenager.ActiveFistTrackingMode == FistTrackingMode.None ||
                        kinectMenager.ActiveFistTrackingMode == FistTrackingMode.Left ||
                        kinectMenager.ActiveFistTrackingMode == FistTrackingMode.LeftPositionOnly)
                    {
                        if (kinectMenager.ActiveFistTrackingMode == FistTrackingMode.Left)
                        {
                            kinectMenager.ActiveFistTrackingMode = FistTrackingMode.Right;
                        }
                        else
                        {
                            kinectMenager.ActiveFistTrackingMode = FistTrackingMode.RightPositionOnly;
                        }
                    }
                    isActiveHand = true;
                }

                if (activeLevel != null && (//activeLevel.Status == LevelStatus.Paused || 
                    activeLevel.Status == LevelStatus.Fail || activeLevel.Status == LevelStatus.Finished))
                {
                    ExitLevel();
                }                
            }
        }
        void waveLeftHand_OnGestureSucces(GestureEventArgs args)
        {
            if (kinectMenager.CalibrationFinish)
            {
                if (activeMenu != null && activeMenu.State == MenuState.Visible && isActiveHand)
                {
                    activeMenu.InvokeOnEscape();
                }

                if (activeLevel == null && !isActiveHand)
                {
                    activeHand = FistType.Left;
                    riseAndDropRightHand.Enable();
                    waveRightHand.Disable();
                    if (kinectMenager.ActiveFistTrackingMode == FistTrackingMode.None ||
                        kinectMenager.ActiveFistTrackingMode == FistTrackingMode.Right ||
                        kinectMenager.ActiveFistTrackingMode == FistTrackingMode.RightPositionOnly)
                    {
                        if (kinectMenager.ActiveFistTrackingMode == FistTrackingMode.Right)
                        {
                            kinectMenager.ActiveFistTrackingMode = FistTrackingMode.Left;
                        }
                        else 
                        {
                            kinectMenager.ActiveFistTrackingMode = FistTrackingMode.LeftPositionOnly;
                        }
                    }
                    isActiveHand = true;
                }

                if (activeLevel != null && (//activeLevel.Status == LevelStatus.Paused)
                    activeLevel.Status == LevelStatus.Fail || activeLevel.Status == LevelStatus.Finished))
                {
                    ExitLevel();
                }                
            }
        }
        void riseAndDropRightHand_OnGestureSucces(GestureEventArgs args)
        {
            if (activeMenu.State == MenuState.Hidden)
            {
                if (activeLevel != null)
                {
                    if (activeLevel.Status == LevelStatus.Fail)
                    {
                        RestartLevel();
                        return;
                    }

                    if (activeLevel.Status == LevelStatus.Finished)
                    {
                        NextLevel();
                        return;
                    }
                }

                if (!kinectMenager.TranslationGestureEnable && !kinectMenager.RotationGestureEnable && !kinectMenager.ScaleGestureEnable)
                {
                    activeObject = activeLevel.GetActiveGameObject();
                }
            }
            else
            {
                activeMenu.GetActiveElement().InvokeOnEnter();
            }
        }
        void SpeechRecognizer_DOWN(object sender, EventArgs e)
        {
            activeObject = activeLevel.GetActiveGameObject();
        }        

        void NewGame_OnEnter(object sender, EventArgs e)
        {
            levelCounter = 0;
            activeMenu.Hide();
            activeLevel = levels[levelCounter];
            BoundingBox workArea = activeLevel.GetLevelWorkArea();
            kinectMenager.SetWorkArea(workArea.Min.X, workArea.Min.Y, workArea.Min.Z, workArea.Max.X, workArea.Max.Y, workArea.Max.Z);
            activeLevel.ActivateLevel();
        }
        void Levels_OnEnter(object sender, EventArgs e)
        {
            activeMenu.Hide();

            levelsMenu.MenuElements.Clear();

            float rot = 0;
            int id = 0;

            foreach (var level in levels)
            {
                //if (level.Status == LevelStatus.Finished)
                {
                    MenuElement elem = new MenuElement(models[(id+1).ToString()], Vector3.One * 5, rot, 15, 10, id);
                    levelsMenu.MenuElements.Add(elem);
                    elem.OnEnter += new EventHandler(ChoiceLevel_OnEnter);

                    rot += 45;
                    id++;
                }
            }

            activeMenu = levelsMenu;
            activeMenu.Show();
        }
        void ChangeHand_OnEnter(object sender, EventArgs e)
        {
            isActiveHand = false;
            riseAndDropRightHand.Disable();
            waveLeftHand.Enable();
            waveRightHand.Enable();
        }
        void Exit_OnEnter(object sender, EventArgs e)
        {
            this.Exit();
        }
        void ChoiceLevel_OnEnter(object sender, EventArgs e)
        {
            MenuElementEventArgs args = (MenuElementEventArgs)e;

            activeMenu.Hide();
            levelCounter = args.id;
            activeLevel = levels[levelCounter];
            activeLevel.RestartLevel();
            BoundingBox workArea = activeLevel.GetLevelWorkArea();
            kinectMenager.SetWorkArea(workArea.Min.X, workArea.Min.Y, workArea.Min.Z, workArea.Max.X, workArea.Max.Y, workArea.Max.Z);
            activeLevel.ActivateLevel();            
        }
        void LevelMenuExit_OnEnter(object sender, EventArgs e)
        {
            activeMenu.Hide();
            activeMenu = mainMenu;
            activeMenu.Show();
        }
       
        void ExitLevel()
        {
            activeLevel.RestartLevel();
            activeLevel = null;

            activeMenu = mainMenu;
            activeMenu.Show();
        }
        void NextLevel()
        {
            activeLevel.DeactivateLevel();
            if (levelCounter < levels.Count - 1)
            {
                activeLevel = levels[++levelCounter];
                BoundingBox workArea = activeLevel.GetLevelWorkArea();
                kinectMenager.SetWorkArea(workArea.Min.X, workArea.Min.Y, workArea.Min.Z, workArea.Max.X, workArea.Max.Y, workArea.Max.Z);
                activeLevel.ActivateLevel();
            }
        }
        void RestartLevel()
        {
            activeLevel.RestartLevel();
            BoundingBox workArea = activeLevel.GetLevelWorkArea();
            kinectMenager.SetWorkArea(workArea.Min.X, workArea.Min.Y, workArea.Min.Z, workArea.Max.X, workArea.Max.Y, workArea.Max.Z);
            activeLevel.ActivateLevel();
        }
        void PauseLevel()
        {
            activeLevel.Status = LevelStatus.Paused;
            kinectMenager.TranslationGestureEnable = false;
            kinectMenager.RotationGestureEnable = false;
            kinectMenager.ScaleGestureEnable = false;
        }
        void UnPauseLevel()
        {
            activeLevel.Status = LevelStatus.Active;
        }

		KeyboardState oldKeyboardState, currentKeyboardState;

        float lastZoom;
				
		protected override void Update(GameTime gameTime)
		{
            if (activeMenu.State == MenuState.Visible || (activeLevel != null && activeLevel.Status != LevelStatus.Paused))
            {
                World.StepSimulation((float)gameTime.ElapsedGameTime.TotalSeconds);
            }

			oldKeyboardState = currentKeyboardState;
			currentKeyboardState = Keyboard.GetState();         

            #region Camera - Keyboard

            if (activeMenu.State == MenuState.Visible)
            {
                if (currentKeyboardState.IsKeyDown(Keys.Left) && oldKeyboardState.IsKeyUp(Keys.Left))
                {
                    activeMenu.NextChoice();
                }
                if (currentKeyboardState.IsKeyDown(Keys.Right) && oldKeyboardState.IsKeyUp(Keys.Right))
                {
                    activeMenu.PreviousChoice();
                }
                if (currentKeyboardState.IsKeyDown(Keys.Enter) && oldKeyboardState.IsKeyUp(Keys.Enter))
                {
                    activeMenu.GetActiveElement().InvokeOnEnter();
                }
                if (currentKeyboardState.IsKeyDown(Keys.Escape) && oldKeyboardState.IsKeyUp(Keys.Escape))
                {
                    activeMenu.InvokeOnEscape();
                }
            }
            else if (activeMenu.State == MenuState.Hidden)
            {
                if (currentKeyboardState.IsKeyDown(Keys.A))
                {
                    Camera.HorizontalAngle -= 0.03f;
                }
                if (currentKeyboardState.IsKeyDown(Keys.D))
                {
                    Camera.HorizontalAngle += 0.03f;
                }
                if (currentKeyboardState.IsKeyDown(Keys.W))
                {
                    Camera.VerticalAngle -= 0.03f;
                }
                if (currentKeyboardState.IsKeyDown(Keys.S))
                {
                    Camera.VerticalAngle += 0.03f;
                }
                if (currentKeyboardState.IsKeyDown(Keys.Z))
                {
                    Camera.Zoom -= 1.0f;
                }
                if (currentKeyboardState.IsKeyDown(Keys.X))
                {
                    Camera.Zoom += 1.0f;
                }
            }           

            #endregion

            #region Other - Keyboard

            if (activeMenu.State == MenuState.Hidden)
            {
                if (currentKeyboardState.IsKeyDown(Keys.F1) && oldKeyboardState.IsKeyUp(Keys.F1))
                {
                    foreach (var level in levels)
                    {
                        level.RestartLevel();
                    }

                    levelCounter = 0;
                    activeLevel = levels[levelCounter];
                    activeLevel.ActivateLevel();
                }
                if (currentKeyboardState.IsKeyDown(Keys.F2) && oldKeyboardState.IsKeyUp(Keys.F2))
                {
                    if (activeLevel != null)
                    {
                        activeLevel.RestartLevel();
                        activeLevel.ActivateLevel();
                    }
                }
                if (currentKeyboardState.IsKeyDown(Keys.Escape) && oldKeyboardState.IsKeyUp(Keys.Escape))
                {
                    ExitLevel();
                }
                if (currentKeyboardState.IsKeyDown(Keys.V) && oldKeyboardState.IsKeyUp(Keys.V))
                {                    
                    if (activeLevel.Status == LevelStatus.Active)
                    {
                        PauseLevel();
                    }
                    else if(activeLevel.Status == LevelStatus.Paused)
                    {
                        UnPauseLevel();
                    }
                }

                if (currentKeyboardState.IsKeyDown(Keys.Space) && oldKeyboardState.IsKeyUp(Keys.Space))
                {
                    if (activeLevel != null)
                    {
                        if (activeLevel.Status != LevelStatus.Paused)
                        {
                            activeObject = activeLevel.GetActiveGameObject();
                        }

                        if (activeLevel.Status == LevelStatus.Fail)
                        {
                            RestartLevel();
                        }

                        if (activeLevel.Status == LevelStatus.Finished)
                        {                            
                            NextLevel();
                        }
                    }
                }
            }

            #endregion

            #region Object - Keyboard

            if (activeMenu.State == MenuState.Hidden)
            {
                if (activeLevel != null && activeLevel.Status != LevelStatus.Paused)
                {
                    if (activeObject != null)
                    {
                        if (currentKeyboardState.IsKeyDown(Keys.J))
                        {
                            activeObject.LocalTranslation *= Matrix.CreateTranslation(Vector3.Transform(Vector3.Left * 0.1f, Matrix.CreateRotationY(Camera.HorizontalAngle)));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.L))
                        {
                            activeObject.LocalTranslation *= Matrix.CreateTranslation(Vector3.Transform(Vector3.Right * 0.1f, Matrix.CreateRotationY(Camera.HorizontalAngle)));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.I))
                        {
                            activeObject.LocalTranslation *= Matrix.CreateTranslation(Vector3.Transform(Vector3.Forward * 0.1f, Matrix.CreateRotationY(Camera.HorizontalAngle)));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.K))
                        {
                            activeObject.LocalTranslation *= Matrix.CreateTranslation(Vector3.Transform(Vector3.Backward * 0.1f, Matrix.CreateRotationY(Camera.HorizontalAngle)));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.N))
                        {
                            activeObject.LocalTranslation *= Matrix.CreateTranslation(Vector3.Up * 0.1f);
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.M))
                        {
                            activeObject.LocalTranslation *= Matrix.CreateTranslation(Vector3.Down * 0.1f);
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.O))
                        {
                            activeObject.LocalRotation *= Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(-3.0f));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.P))
                        {
                            activeObject.LocalRotation *= Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.ToRadians(+3.0f));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.Y))
                        {
                            activeObject.LocalRotation *= Matrix.CreateFromAxisAngle(Vector3.Transform(Vector3.Left, Matrix.CreateRotationY(Camera.HorizontalAngle)), MathHelper.ToRadians(-3.0f));
                        }
                        if (currentKeyboardState.IsKeyDown(Keys.U))
                        {
                            activeObject.LocalRotation *= Matrix.CreateFromAxisAngle(Vector3.Transform(Vector3.Left, Matrix.CreateRotationY(Camera.HorizontalAngle)), MathHelper.ToRadians(3.0f));
                        }
                    }
                }
            }

            #endregion            
            
            if (activeMenu.State == MenuState.Hidden)
            {
                if (kinectMenager.KinectIsConnected && kinectMenager.CalibrationFinish)
                {
                    #region Camera and Object - Kinect

                    if (Math.Abs(cameraRotateYTmp) < 0.01)
                    {
                        cameraRotateYTmp = 0;
                    }
                    else
                    {
                        cameraRotateYTmp -= (cameraRotateYTmp * 0.05f);
                    }
                    if (Math.Abs(cameraRotateXTmp) < 0.01)
                    {
                        cameraRotateXTmp = 0;
                    }
                    else
                    {
                        cameraRotateXTmp -= (cameraRotateXTmp * 0.05f);
                    }

                    Camera.HorizontalAngle += cameraRotateYTmp;
                    Camera.VerticalAngle += cameraRotateXTmp;

                    bool beforeZoom = kinectMenager.ScaleGestureEnable;

                    float zoomd = kinectMenager.GetObjectScale();

                    bool afterZoom = kinectMenager.ScaleGestureEnable;

                    if (afterZoom && !beforeZoom)
                    {
                        lastZoom = Camera.Zoom;
                    }

                    if (afterZoom)
                    {
                        Camera.Zoom = lastZoom - zoomd * 20;
                    }

                    if (activeObject != null && activeLevel != null && activeLevel.Status != LevelStatus.Paused)
                    {
                        if (!kinectMenager.TranslationGestureEnable)
                        {
                            bool beforeUpdate = kinectMenager.RotationGestureEnable;

                            Vector3 rotation = kinectMenager.GetObjectRotation();

                            bool afterUpdate = kinectMenager.RotationGestureEnable;

                            if (beforeUpdate && !afterUpdate)
                            {
                                activeObject.BaseRotation *= activeObject.LocalRotation;
                                activeObject.LocalRotation = Matrix.Identity;
                            }

                            if (afterUpdate)
                            {
                                Matrix newOrientation = Matrix.CreateFromAxisAngle(Vector3.Normalize(Vector3.Transform(Vector3.Left, Matrix.CreateRotationY(Camera.HorizontalAngle))), rotation.X) *
                                    Matrix.CreateFromAxisAngle(Vector3.Up, rotation.Y) *
                                    Matrix.CreateFromAxisAngle(Vector3.Normalize(Vector3.Transform(Vector3.Backward, Matrix.CreateRotationY(Camera.HorizontalAngle))), rotation.Z);

                                activeObject.LocalRotation = newOrientation;
                            }
                        }

                        if (!kinectMenager.RotationGestureEnable)
                        {
                            bool beforeUpdate = kinectMenager.TranslationGestureEnable;

                            Vector3 newTranslationVector = kinectMenager.GetObjectTranslation(activeHand);

                            bool afterUpdate = kinectMenager.TranslationGestureEnable;

                            if (beforeUpdate && !afterUpdate)
                            {
                                activeObject.BaseTranslation *= activeObject.LocalTranslation;
                                activeObject.LocalTranslation = Matrix.Identity;
                            }

                            if (afterUpdate)
                            {
                                Matrix newTranslation = Matrix.CreateTranslation(Vector3.Transform(newTranslationVector, Matrix.CreateRotationY(Camera.HorizontalAngle)));

                                activeObject.LocalTranslation = newTranslation;
                            }
                        }
                    }

                    #endregion
                }                
            }

            if (activeMenu.State == MenuState.Visible)
            {
                activeMenu.Update(gameTime);
            }
            else
            {
                #region Level Update

                if (activeLevel != null)
                {
                    activeLevel.Update(gameTime);
                }

                #endregion
            }

            Camera.Update(gameTime);
            kinectMenager.Update();

            tmpa += 0.01f;

            if (tmpb < -20)
            {
                tmpc = 0.3f;
            }
            if (tmpb > 20)
            {
                tmpc = -0.3f;
            }

            tmpb += tmpc;

			base.Update(gameTime);
		}

        float tmpb = 0;
        float tmpc = 0.3f;

        float tmpa = 0;

		SpriteFont font;
		protected override void Draw(GameTime gameTime)
		{
            GraphicsDevice.Clear(Color.CornflowerBlue);
            if (kinectMenager.CalibrationFinish)
            {
                GraphicsDevice.SetRenderTarget(shadowRenderTarget);
                GraphicsDevice.Clear(Color.White);

                if (activeMenu.State == MenuState.Hidden)
                {
                    DrawLevel(activeLevel, "ShadowMapRender");
                }
                else
                {
                    DrawMenu(activeMenu, "ShadowMapRender");
                }

                shadowMapTexture = (Texture2D)shadowRenderTarget;

                GraphicsDevice.BlendState = BlendState.Opaque;
                GraphicsDevice.DepthStencilState = DepthStencilState.Default;
                GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
                GraphicsDevice.SamplerStates[1] = SamplerState.LinearWrap;

                GraphicsDevice.SetRenderTarget(screenRenderTarget);
                GraphicsDevice.Clear(Color.White);

                if (activeMenu.State == MenuState.Hidden)
                {
                    DrawLevel(activeLevel, "Unlit");
                }
                else
                {
                    DrawMenu(activeMenu, "Unlit");
                }

                GraphicsDevice.SetRenderTarget(null);
                screenMapTexture = (Texture2D)screenRenderTarget;
                GraphicsDevice.Clear(Color.CornflowerBlue);

                if (activeMenu.State == MenuState.Hidden)
                {
                    DrawLevel(activeLevel, "Scene");
                }
                else
                {
                    DrawMenu(activeMenu, "Scene");
                }

                if (activeMenu.State == MenuState.Visible)
                {
                    DrawModelOnScreen2D(activeMenu.GetActiveElement().ElementObject.Model, new Vector3(10), Vector3.Zero, new Vector3(0, -250, 0));
                    DrawModelOnScreen2D(models["activehand"], new Vector3(5), Vector3.Zero, new Vector3(450, 250, 0));

                    if (isActiveHand)
                    {
                        if (activeHand == FistType.Left)
                        {
                            DrawModelOnScreen2D(models["left"], new Vector3(10), new Vector3(0, MathHelper.ToRadians(tmpb), 0), new Vector3(450, 200, 0));
                        }
                        else
                        {
                            DrawModelOnScreen2D(models["right"], new Vector3(10), new Vector3(0, MathHelper.ToRadians(tmpb), 0), new Vector3(450, 200, 0));
                        }
                    }
                    else
                    {
                        DrawModelOnScreen2D(models["none"], new Vector3(10), new Vector3(0, MathHelper.ToRadians(tmpb), 0), new Vector3(450, 200, 0));
                        DrawModelOnScreen2D(models["wavetoselect"], new Vector3(20), Vector3.Zero, new Vector3(0, 200, 0));
                    }
                }

                if (activeMenu.State == MenuState.Hidden)
                {
                    if (activeLevel != null)
                    {
                        GameObject nextGameObject = activeLevel.GetNextActiveGameObject();
                        if (nextGameObject != null)
                        {
                            DrawModelOnScreen2D(nextGameObject.Model, new Vector3(90), new Vector3(5, tmpa, 0), new Vector3(420, 180, 0));
                        }

                        if (activeLevel.Status == LevelStatus.Paused)
                        {
                            DrawModelOnScreen2D(models["paused"], new Vector3(15 + tmpb/8), Vector3.Zero, new Vector3(0, 0, 0));

                        }
                    }

                    spriteBatch.Begin();
                    if (kinectMenager.TranslationGestureEnable)
                    {
                        spriteBatch.Draw(hand0Texture, new Rectangle(20, 20, hand0Texture.Width / 5, hand0Texture.Height / 5), Color.White);
                    }
                    else if (kinectMenager.RotationGestureEnable)
                    {
                        if (kinectMenager.RotateOnlyX)
                        {
                            spriteBatch.Draw(rotateXTexture, new Rectangle(20, 20, objectTexture.Width / 5, objectTexture.Height / 5), Color.White);
                        }
                        else if (kinectMenager.RotateOnlyY)
                        {
                            spriteBatch.Draw(rotateYTexture, new Rectangle(20, 20, objectTexture.Width / 5, objectTexture.Height / 5), Color.White);
                        }
                        else if (kinectMenager.RotateOnlyZ)
                        {
                            spriteBatch.Draw(rotateZTexture, new Rectangle(20, 20, objectTexture.Width / 5, objectTexture.Height / 5), Color.White);
                        }
                        else
                        {
                            spriteBatch.Draw(rotateTexture, new Rectangle(20, 20, objectTexture.Width / 5, objectTexture.Height / 5), Color.White);
                        }
                    }
                    else if (kinectMenager.ScaleGestureEnable)
                    {
                        spriteBatch.Draw(hand1Texture, new Rectangle(20, 20, objectTexture.Width / 5, objectTexture.Height / 5), Color.White);
                    }

                    spriteBatch.End();
                }
            }
            else
            {
                if (!kinectMenager.KinectIsConnected)
                {
                    DrawModelOnScreen2D(models["searchingkinect"], new Vector3(15), new Vector3(0, MathHelper.ToRadians(tmpb), 0), new Vector3(0, 180, 0));
                }
                else
                {
                    DrawModelOnScreen2D(models["calibration"], new Vector3(15 + tmpb/8), Vector3.Zero, new Vector3(0, 230, 0));


                    if (!kinectMenager.FindSkeleton)
                    {
                        DrawModelOnScreen2D(models["activeskeleton"], new Vector3(15), new Vector3(0, MathHelper.ToRadians(tmpb), 0), new Vector3(0, 50, 0));
                    }
                    else
                    {
                        KinectMenager k = kinectMenager;

                        #region Draw Fist Calibration - With State
                        if (!k.RightFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.Right)
                        {
                            if (!k.RightFistCalibrationActive)
                            {
                                DrawModelOnScreen2D(models["preparefor"], new Vector3(15), Vector3.Zero, new Vector3(0, 50, 0));
                            }

                            switch (k.WhatIsCalibrated)
                            {
                                case 1:
                                    {
                                        DrawModelOnScreen2D(models["FROH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0)); 
                                        break;
                                    }
                                case 2:
                                    {
                                        DrawModelOnScreen2D(models["FRCH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0)); 
                                        break;
                                    }
                                case 3:
                                    {
                                        DrawModelOnScreen2D(models["NROH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0)); 
                                        break;
                                    }
                                case 4:
                                    {
                                        DrawModelOnScreen2D(models["NRCH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0)); 
                                        break;
                                    }
                            }
                        }

                        if ((!k.LeftFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.Left))
                        {
                            if (!k.LeftFistCalibrationActive)
                            {
                                DrawModelOnScreen2D(models["preparefor"], new Vector3(15), Vector3.Zero, new Vector3(0, 50, 0));
                            }

                            switch (k.WhatIsCalibrated)
                            {
                                case 1:
                                    {
                                        DrawModelOnScreen2D(models["FLOH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0));
                                        break;
                                    }
                                case 2:
                                    {
                                        DrawModelOnScreen2D(models["FLCH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0));
                                        break;
                                    }
                                case 3:
                                    {
                                        DrawModelOnScreen2D(models["NLOH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0));
                                        break;
                                    }
                                case 4:
                                    {
                                        DrawModelOnScreen2D(models["NLCH"], new Vector3(15), Vector3.Zero, new Vector3(0, 0, 0));
                                        break;
                                    }
                            }
                        }
                        #endregion

                        #region Draw Fist Calibration - Position Only
                        if (!k.RightFistCalibrationFinish &&
                            (k.ActiveFistTrackingMode == FistTrackingMode.RightPositionOnly ||
                            k.ActiveFistTrackingMode == FistTrackingMode.BothPositionOnly))
                        {
                            DrawModelOnScreen2D(models["MMR"], new Vector3(15), Vector3.Zero, new Vector3(0, 50, 0));
                        }

                        if ((!k.LeftFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.LeftPositionOnly) ||
                            (k.RightFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.BothPositionOnly))
                        {
                            DrawModelOnScreen2D(models["MML"], new Vector3(15), Vector3.Zero, new Vector3(0, 50, 0));
                        }
                        #endregion
                    }
                }
            }

			DebugShapeRenderer.Draw(gameTime, Camera.viewMatrix, Camera.projectionMatrix);
			DrawDebugFromKinectMenager(kinectMenager);

			base.Draw(gameTime);
		}

        private void DrawMenu(Menu menu, String technique)
        {
            DrawGameObject(menu.Ground, technique);

            foreach (var o in menu.MenuObjects)
            {
                DrawGameObject(o, technique);
            }

            foreach (var e in menu.MenuElements)
            {
                DrawGameObject(e.ElementObject, technique);
            }
        }

		private void DrawLevel(Level level, String technique)
		{
            if (level != null)
            {
                foreach (var sgo in level.StaticGameObjects)
                {
                    DrawGameObject(sgo, technique);
                }

                foreach (var dgo in level.GameObjects)
                {
                    DrawGameObject(dgo, technique);
                }

                foreach (var go in level.SuccessFailObjects)
                {
                    DrawGameObject(go, technique);
                }

                foreach (var go in level.Timer.SecondsObject)
                {
                    //DrawModelOnScreen2D(go.Model, go.World);
                    if(technique != "ShadowMapRender")
                    DrawGameObject(go, technique);
                }
            }
		}

		private void DrawGameObject(GameObject go, String technique)
		{
			if (go != null && go.Visible)
			{
				if (go.type == GameObjectType.MODEL)
				{
					Matrix[] transforms = new Matrix[go.Model.Bones.Count];
					go.Model.CopyAbsoluteBoneTransformsTo(transforms);

					foreach (ModelMesh mesh in go.Model.Meshes)
					{
						foreach (Effect effect in mesh.Effects)
						{
							effect.CurrentTechnique = effect.Techniques[technique];

							if (effect is BasicEffect)
							{
								BasicEffect e = (BasicEffect)effect;
								e.EnableDefaultLighting();
								e.View = Camera.viewMatrix;
								e.Projection = Camera.projectionMatrix;
								e.World = transforms[mesh.ParentBone.Index] * go.World;
							}
							else
							{
								effect.Parameters["view"].SetValue(Camera.viewMatrix);
								effect.Parameters["projection"].SetValue(Camera.projectionMatrix);

								Matrix world = transforms[mesh.ParentBone.Index] * go.World;

								effect.Parameters["world"].SetValue(world);
								effect.Parameters["worldInverseTranspose"].SetValue(Matrix.Transpose(Matrix.Invert(world)));

								effect.Parameters["worldViewProj"].SetValue(world * Camera.viewMatrix * Camera.projectionMatrix);
								
								Light light = lights[0];

								int i = 0;
								foreach (var l in lights)
								{
									EffectParameter p = effect.Parameters["light"].Elements[i];
									p.StructureMembers["dir"].SetValue(l.Output.dir);
									p.StructureMembers["pos"].SetValue(l.Output.pos);
									p.StructureMembers["ambient"].SetValue(l.Output.ambient);
									p.StructureMembers["diffuse"].SetValue(l.Output.diffuse);
									p.StructureMembers["specular"].SetValue(l.Output.specular);
									p.StructureMembers["spotInnerCone"].SetValue(l.Output.spotInnerCone);
									p.StructureMembers["spotOuterCone"].SetValue(l.Output.spotOuterCone);
									p.StructureMembers["radius"].SetValue(l.Output.radius);
									i++;
								}

								Matrix lightView = Matrix.CreateLookAt(light.Output.pos, Vector3.Zero, Vector3.Up);
								Matrix lightProjection = Matrix.CreateOrthographic(50.0f, 50.0f, 1.0f, 100.0f);

								Matrix lightViewProjection = world * lightView * lightProjection;

								effect.Parameters["lightViewProj"].SetValue(lightViewProjection);

								effect.Parameters["cameraPos"].SetValue(Camera.position);
								effect.Parameters["globalAmbient"].SetValue(new XNA.Vector4(1));

								float offset = 0.5f + (0.5f / (float)2048);

								Matrix textureMatrixAdj = new Matrix(0.5f, 0.0f, 0.0f, 0.0f,
																	0.0f, -0.5f, 0.0f, 0.0f,
																	0.0f, 0.0f, 1.0f, 0.0f,
																	offset, offset, 0.0f, 1.0f);

								Matrix textureMatrix = lightViewProjection * textureMatrixAdj;

								effect.Parameters["textureMatrix"].SetValue(textureMatrix);

								if (technique != "ShadowMapRender")
								{
									effect.Parameters["shadowMapTexture"].SetValue(shadowMapTexture);
								}

								if (technique != "Unlit")
								{
									effect.Parameters["screenMapTexture"].SetValue(screenMapTexture);
								}
							}
						}
						mesh.Draw();
					}
				}

				if (go.type == GameObjectType.BOX)
				{
					BoundingBox boxTransform = new BoundingBox();
					boxTransform.Min = Vector3.Transform(go.Box.Min, go.World);
					boxTransform.Max = Vector3.Transform(go.Box.Max, go.World);
					Game.DebugShapeRenderer.AddBoundingBox(boxTransform, Color.Yellow);
				}
			}
		}

		private void DrawDebugFromKinectMenager(KinectMenager k)
		{
			spriteBatch.Begin();

            #region Draw Fist Texture            
            if (k.LeftFistAreaTexture != null)
			{
				spriteBatch.Draw(Texture2DFromBitmap(k.LeftFistAreaTexture), new Rectangle(0, graphicsDevice.Viewport.Height - k.HandRectHalfY * 4 + 1, k.HandRectHalfX * 4 + 1, k.HandRectHalfY * 4 + 1), Color.White);
			}

			if (k.RightFistAreaTexture != null)
			{
				spriteBatch.Draw(Texture2DFromBitmap(k.RightFistAreaTexture), new Rectangle(graphicsDevice.Viewport.Width - k.HandRectHalfX * 4 + 1, graphicsDevice.Viewport.Height - k.HandRectHalfY * 4 + 1, k.HandRectHalfX * 4 + 1, k.HandRectHalfY * 4 + 1), Color.White);
            }
            #endregion            

            /*if (!k.KinectIsConnected)
            {
                spriteBatch.DrawString(font, "SZUKAM URZADZENIE ... ", new Vector2(300, 60), Color.Red);
            }
            else if (!k.CalibrationFinish)
            {
                spriteBatch.DrawString(font, "KALIBRACJA. NIE WYLACZAJ URZADZENIA.", new Vector2(300, 60), Color.Red);

                if (!k.FindSkeleton)
                {
                    spriteBatch.DrawString(font, "Szukam szkieletu ...", new Vector2(300, 90), Color.Red);
                }

                if (k.FindSkeleton)
                {
                    #region Draw Fist Calibration - With State                    
                    if ( !k.RightFistCalibrationFinish && 
                        (k.ActiveFistTrackingMode == FistTrackingMode.Right|| k.ActiveFistTrackingMode == FistTrackingMode.Both) )
                    {
                        if (!k.RightFistCalibrationActive)
                        {
                            spriteBatch.DrawString(font, "Przygotuj sie na: ", new Vector2(350, 90), Color.Red);
                        }

                        switch (k.WhatIsCalibrated)
                        {
                            case 1:
                                {
                                    spriteBatch.DrawString(font, "RIGHT FAR OPENED  " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                            case 2:
                                {
                                    spriteBatch.DrawString(font, "RIGHT FAR CLOSED  " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                            case 3:
                                {
                                    spriteBatch.DrawString(font, "RIGHT NEAR OPENED " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                            case 4:
                                {
                                    spriteBatch.DrawString(font, "RIGHT NEAR CLOSED " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                        }
                    }

                    if ( (!k.LeftFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.Left ) ||
                        (k.ActiveFistTrackingMode == FistTrackingMode.Both && k.RightFistCalibrationFinish) )
                    {
                        if (!k.LeftFistCalibrationActive)
                        {
                            spriteBatch.DrawString(font, "Przygotuj sie na: ", new Vector2(350, 90), Color.Red);
                        }

                        switch (k.WhatIsCalibrated)
                        {
                            case 1:
                                {
                                    spriteBatch.DrawString(font, "LEFT FAR OPENED  " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                            case 2:
                                {
                                    spriteBatch.DrawString(font, "LEFT FAR CLOSED  " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                            case 3:
                                {
                                    spriteBatch.DrawString(font, "LEFT NEAR OPENED " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                            case 4:
                                {
                                    spriteBatch.DrawString(font, "LEFT NEAR CLOSED " + k.CalibrationBufferCounter.ToString() + " / " + k.CalibrationBufferLength.ToString(), new Vector2(350, 120), Color.Red);
                                    break;
                                }
                        }
                    }
                    #endregion

                    #region Draw Fist Calibration - Position Only                    
                    if ( !k.RightFistCalibrationFinish && 
                        (k.ActiveFistTrackingMode == FistTrackingMode.RightPositionOnly ||
                        k.ActiveFistTrackingMode == FistTrackingMode.BothPositionOnly))
                    {
                        spriteBatch.DrawString(font, "Znajdz maksymalne i minimalne polozenie PRAWEJ dloni", new Vector2(100, 90), Color.Red);
                    }

                    if ( (!k.LeftFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.LeftPositionOnly) ||
                        (k.RightFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.BothPositionOnly))
                    {
                        spriteBatch.DrawString(font, "Znajdz maksymalne i minimalne polozenie LEWEJ dloni", new Vector2(100, 90), Color.Red);
                    }
                    #endregion
                }
            }
            else*/
            if(k.CalibrationFinish)
            {
                #region Draw After Calibration
                
                if (k.RightFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.Right)
                {
                    Color fistColor = new Color();

                    if (k.RightFistState == FistState.Open)
                    {
                        fistColor = Color.Green;
                    }
                    else if (k.RightFistState == FistState.Close)
                    {
                        fistColor = Color.Red;
                    }

                    spriteBatch.DrawString(font, "FAR OPENED  : " + k.farOpenedRightArea.ToString(), new Vector2(20, 390), Color.Black);
                    spriteBatch.DrawString(font, "FAR CLOSED  : " + k.farClosedRightArea.ToString(), new Vector2(20, 420), Color.Black);
                    spriteBatch.DrawString(font, "NEAR OPENED : " + k.nearOpenedRightArea.ToString(), new Vector2(20, 450), Color.Black);
                    spriteBatch.DrawString(font, "NEAR CLOSED : " + k.nearClosedRightArea.ToString(), new Vector2(20, 480), Color.Black);
                    spriteBatch.DrawString(font, "HAND AREA : " + k.RightFistArea.ToString(), new Vector2(20, 510), fistColor);
                    spriteBatch.DrawString(font, "FAR Z: " + k.minRightZ.ToString(), new Vector2(20, 540), Color.Black);
                    spriteBatch.DrawString(font, "NEAR Z: " + k.maxRightZ.ToString(), new Vector2(20, 570), Color.Black);
                }

                if (k.LeftFistCalibrationFinish && k.ActiveFistTrackingMode == FistTrackingMode.Left)
                {
                    Color fistColor = new Color();

                    if (k.LeftFistState == FistState.Open)
                    {
                        fistColor = Color.Green;
                    }
                    else if (k.LeftFistState == FistState.Close)
                    {
                        fistColor = Color.Red;
                    }

                    spriteBatch.DrawString(font, "FAR OPENED  : " + k.farOpenedLeftArea.ToString(), new Vector2(20, 150), Color.Blue);
                    spriteBatch.DrawString(font, "FAR CLOSED  : " + k.farClosedLeftArea.ToString(), new Vector2(20, 180), Color.Blue);
                    spriteBatch.DrawString(font, "NEAR OPENED : " + k.nearOpenedLeftArea.ToString(), new Vector2(20, 210), Color.Blue);
                    spriteBatch.DrawString(font, "NEAR CLOSED : " + k.nearClosedLeftArea.ToString(), new Vector2(20, 240), Color.Blue);
                    spriteBatch.DrawString(font, "HAND AREA : " + k.LeftFistArea.ToString(), new Vector2(20, 270), fistColor);
                    spriteBatch.DrawString(font, "FAR Z: " + k.minLeftZ.ToString(), new Vector2(20, 300), Color.Blue);
                    spriteBatch.DrawString(font, "NEAR Z: " + k.maxLeftZ.ToString(), new Vector2(20, 330), Color.Blue);
                }

                if (k.RightFistCalibrationFinish &&
                        (k.ActiveFistTrackingMode == FistTrackingMode.RightPositionOnly ||
                        k.ActiveFistTrackingMode == FistTrackingMode.BothPositionOnly))
                {
                    spriteBatch.DrawString(font, "FAR Z: " + k.minRightZ.ToString(), new Vector2(720, 280), Color.Green);
                    spriteBatch.DrawString(font, "NEAR Z: " + k.maxRightZ.ToString(), new Vector2(720, 310), Color.Green);
                }

                if (k.LeftFistCalibrationFinish &&
                        (k.ActiveFistTrackingMode == FistTrackingMode.LeftPositionOnly ||
                        k.ActiveFistTrackingMode == FistTrackingMode.BothPositionOnly))
                {
                    spriteBatch.DrawString(font, "FAR Z: " + k.minLeftZ.ToString(), new Vector2(20, 280), Color.Blue);
                    spriteBatch.DrawString(font, "NEAR Z: " + k.maxLeftZ.ToString(), new Vector2(20, 310), Color.Blue);
                }

                #endregion
            }
            
			spriteBatch.End();
		}

        private void DrawModelOnScreen2D(Model model, Matrix world)
        {
            Vector3 s, po;
            Quaternion r;
            world.Decompose(out s, out r, out po);

            DrawModelOnScreen2D(model, s, Vector3.Zero, po);
        }

        private void DrawModelOnScreen2D(Model model, Vector3 scale, Vector3 rotate, Vector3 pos)
        {
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            Matrix world = Matrix.Identity;

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (Effect effect in mesh.Effects)
                {
                    effect.CurrentTechnique = effect.Techniques["PerPixelDirectionalLighting"];

                    if (effect is BasicEffect)
                    {
                        BasicEffect e = (BasicEffect)effect;
                        e.EnableDefaultLighting();
                        e.View = Camera.viewMatrix;
                        e.Projection = Camera.projectionMatrix;
                        e.World = transforms[mesh.ParentBone.Index] * world;
                    }
                    else
                    {
                        Matrix cameraView = Matrix.CreateLookAt(Vector3.Backward * 10, Vector3.Zero, Vector3.Up);
                        Matrix cameraProjection = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, -1000.0f, 1000.0f);

                        effect.Parameters["view"].SetValue(cameraView);
                        effect.Parameters["projection"].SetValue(cameraProjection);

                        Vector3 s, po;
                        Quaternion r;
                        transforms[mesh.ParentBone.Index].Decompose(out s, out r, out po);

                        world = Matrix.CreateScale(s + scale) *
                            Matrix.CreateRotationX(rotate.X) *
                            Matrix.CreateRotationY(rotate.Y) *
                            Matrix.CreateRotationZ(rotate.Z) *
                            Matrix.CreateTranslation(po + pos);

                        effect.Parameters["world"].SetValue(world);
                        effect.Parameters["worldInverseTranspose"].SetValue(Matrix.Transpose(Matrix.Invert(world)));
                        
                        EffectParameter p = effect.Parameters["light"].Elements[0];
                        p.StructureMembers["dir"].SetValue(Vector3.Right + Vector3.Up);//Vector3.Transform(Vector3.Left, Matrix.CreateRotationY(-tmpa*3)));
                        p.StructureMembers["ambient"].SetValue(new XNA.Vector4(0.05f, 0.09f, 0.1f, 1.0f));
                        p.StructureMembers["diffuse"].SetValue(new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f));
                        p.StructureMembers["specular"].SetValue(new XNA.Vector4(1.0f, 0.96f, 0.8f, 1.0f));

                        effect.Parameters["cameraPos"].SetValue(Camera.position);
                        effect.Parameters["globalAmbient"].SetValue(new XNA.Vector4(1));
                    }
                }
                mesh.Draw();
            }
        }

		public static Vector3 ToVector3(SkeletonPoint vector)
		{
			return new Vector3(vector.X, vector.Y, vector.Z);
		}

		private Texture2D Texture2DFromBitmap(System.Drawing.Bitmap b)
		{
			using (MemoryStream s = new MemoryStream())
			{
				b.Save(s, System.Drawing.Imaging.ImageFormat.Png);
				s.Seek(0, SeekOrigin.Begin);
				return Texture2D.FromStream(GraphicsDevice, s);
			}
		}
    }	

    public class ObjectCollisionCallback : CollisionWorld.ContactResultCallback
    {
        Level level;
        public ObjectCollisionCallback(Level level)
        {
            this.level = level;
        }

        public override float AddSingleResult(ManifoldPoint cp, CollisionObjectWrapper colObj0Wrap, int partId0, int index0, CollisionObjectWrapper colObj1Wrap, int partId1, int index1)
        {
            level.Status = LevelStatus.Fail;
            return 0;
        }
    }
	
}
